<template>
  <div class="container">
    <h2>图片压缩工具</h2>
    <div class="feature-group">
      <label class="feature-label">工具说明:</label>
      <ul class="feature-list">
        <li class="feature-item">本工具可以压缩 PNG、JPEG、WebP 格式的图片，并转换为 WebP 格式。</li>
        <li class="feature-item">压缩后的图片大小会比原始图片小，但质量可能有所损失。</li>
        <li class="feature-item">PNG格式使用无损压缩，转换为WebP格式可以获得更小的文件大小。</li>
        <li class="feature-item">点击按钮选择要压缩的图片，压缩后的图片会在右侧显示。</li>
      </ul>
    </div>
    <!-- 文件上传 -->
    <div class="list-group">
    <input
      type="file"
      accept="image/*"
      @change="handleFileUpload"
      class="upload-input"
    />

    <!-- 预览区域 -->
    <div v-if="previewUrl" class="preview-container">
      <div class="preview-box">
        <h3>原始图片</h3>
        <img :src="previewUrl" alt="Original Preview" />
        <p>尺寸: {{ originalSize.width }} x {{ originalSize.height }}</p>
        <p>大小: {{ formatFileSize(originalSize.fileSize) }}</p>
        <p>类型: {{ originalMimeType }}</p>
      </div>

      <div class="preview-box">
        <h3>压缩后</h3>
        <img :src="compressedUrl" alt="Compressed Preview" v-if="compressedUrl" />
        <p v-else>压缩中...</p>
        <p>尺寸: {{ compressedSize.width }} x {{ compressedSize.height }}</p>
        <p>大小: {{ compressedSize.fileSize ? formatFileSize(compressedSize.fileSize) : '-' }}</p>
        <p>类型: {{ compressedMimeType }}</p>
      </div>
    </div>

    <!-- 压缩控制 -->
    <div v-if="previewUrl" class="controls">
      <div class="format-group">
      <!-- 格式选择 -->
      <div class="format-selector">
        <label>输出格式：</label>
        <select v-model="fileType">
          <option value="auto">自动 (WebP)</option>
          <option value="jpeg">JPEG</option>
          <option value="png">PNG</option>
          <option value="webp">WebP</option>
        </select>
      </div>

      <!-- 质量控制 -->
      <div v-if="isQualityEnabled" class="quality-control">
        <label>压缩质量: {{ quality * 100 }}%</label>
        <input
          type="range"
          v-model="quality"
          min="0.01"
          max="1"
          step="0.01"
        />
      </div>
      <p v-else>PNG格式使用无损压缩，转换为WebP格式可以获得更小的文件大小</p>

      <!-- 尺寸控制 -->
      <div class="size-control" v-if="fileType.value !== 'auto'">
        <label>宽度：</label>
        <input type="number" v-model="targetWidth" min="1" />
        <label>高度：</label>
        <input type="number" v-model="targetHeight" min="1" />
      </div>
      </div>
      <!-- 压缩按钮 -->
      <button @click="compressImage" :disabled="isCompressing">
        {{ isCompressing ? '压缩中...' : '开始压缩' }}
      </button>

      <!-- 下载按钮 -->
      <a
        v-if="compressedUrl"
        :href="compressedUrl"
        :download="downloadFilename"
        class="download-btn"
      >
        下载压缩图片
      </a>
    </div>
      </div>
  </div>
</template>

<script setup>
// 创建Web Worker
const worker = new Worker(new URL('./imageCompressor.js', import.meta.url));

// 响应式状态
const previewUrl = ref(null);
const compressedUrl = ref(null);
const originalSize = ref({});
const compressedSize = ref({});
const quality = ref(0.7);
const isCompressing = ref(false);
const fileType = ref('webp');
const originalMimeType = ref('');
const targetWidth = ref(null);
const targetHeight = ref(null);

// 监听fileType的变化，当变化时重新压缩图片
watch(fileType, () => {
  if (previewUrl.value) {
    compressImage();
  }
});

// 监听quality的变化，当变化时重新压缩图片
watch(quality, () => {
  if (previewUrl.value) {
    compressImage();
  }
});

// 监听targetWidth或targetHeight的变化，当变化时重新压缩图片
watch([targetWidth, targetHeight], () => {
  if (previewUrl.value) {
    compressImage();
  }
});

// 计算属性
const isQualityEnabled = computed(() =>
  ['jpeg', 'webp'].includes(fileType.value)
);

const downloadFilename = computed(() => {
  const extMap = {
    jpeg: 'jpg',
    auto: 'webp',
    png: 'png',
    webp: 'webp'
  };
  const ext = extMap[fileType.value] || fileType.value;
  return `compressed_image.${ext}`;
});

const compressedMimeType = computed(() => {
  const mimeMap = {
    jpeg: 'image/jpeg',
    png: 'image/png',
    webp: 'image/webp',
    auto: originalMimeType.value === 'image/png' ? 'image/webp' : originalMimeType.value || 'image/webp'
  };
  return mimeMap[fileType.value];
});

// 文件上传处理
const handleFileUpload = (e) => {
  const file = e.target.files[0];
  if (!file) return;

  resetState();
  previewUrl.value = URL.createObjectURL(file);

  const img = new Image();
  img.src = previewUrl.value;
  img.onload = () => {
    originalSize.value = {
      width: img.naturalWidth,
      height: img.naturalHeight,
      fileSize: file.size
    };
    originalMimeType.value = file.type;
  };
};

// 图片压缩方法
const compressImage = () => {
  if (!previewUrl.value) return;

  isCompressing.value = true;

  worker.postMessage({
    previewUrl: previewUrl.value,
    fileType: fileType.value,
    quality: quality.value,
    targetWidth: targetWidth.value,
    targetHeight: targetHeight.value
  });

  worker.onmessage = (event) => {
    const { blob, width, height, error } = event.data;

    if (error) {
      console.error('压缩失败:', error);
      isCompressing.value = false;
      return;
    }

    compressedSize.value = {
      width,
      height,
      fileSize: blob.size
    };

    compressedUrl.value = URL.createObjectURL(blob);
    isCompressing.value = false;
  };

  worker.onerror = (error) => {
    console.error('压缩失败:', error);
    isCompressing.value = false;
  };
};

// 工具函数
const formatFileSize = (bytes) => {
  if (bytes < 1024) return `${bytes} B`;
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(2)} KB`;
  return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
};

const resetState = () => {
  previewUrl.value = null;
  compressedUrl.value = null;
  originalSize.value = {};
  compressedSize.value = {};
  compressedUrl.value = null;
  targetWidth.value = null;
  targetHeight.value = null;
};
</script>

<style scoped>
.container {
  max-width: 1000px;
  width: calc(100% - 60px);
  margin: 40px auto 10px auto;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
  background: #f9f9f9;
}
h2 {
  margin-bottom: 20px;
  text-align: center;
  font-size: 24px;
  color: #17a2b8;
}
.feature-group {
  margin-bottom: 20px;
}

.feature-label {
  display: inline-block;
  margin-bottom: 5px;
  font-weight: bold;
  border-left: 4px solid #17a2b8;
  padding-left: 10px;
}

.feature-list {
  margin: 0;
  padding: 20px;
  border-radius: 4px;
}

.feature-item {
  margin: 0 0 8px 20px;
  font-size: 14px;
  line-height: 1.5;
  list-style-type: disc; /* 列表符号 */
}

.feature-list::marker {
  color: #007bff; /* 圆点颜色 */
  font-size: 16px; /* 圆点大小 */
}

/* 如果你有具体的列表内容，可以在这里添加 */
.feature-list ul {
  margin: 0;
  padding: 0;
  list-style-type: none; /* 先去掉默认样式 */
}

.feature-list ul li::before {
  content: '•'; /* 添加圆点 */
  color: #007bff; /* 圆点颜色 */
  display: inline-block;
  width: 1em;
  margin-left: -1em;
  font-size: 16px; /* 圆点大小 */
}
.list-group {
  display: flex;
  flex-direction: column;
  gap: 20px;
  border: 1px solid #ccc;
}

.preview-container {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
  margin: 10px;
  padding: 10px;
}

.preview-box {
  border: 1px solid #ddd;
  padding: 15px;
  border-radius: 8px;
  background: #fff;
}

.preview-box img {
  max-width: 100%;
  height: auto;
  margin: 10px 0;
}

.controls {
  margin-top: 20px;
  text-align: center;
}
.format-group {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.format-selector {
  margin: 15px 0;
  gap: 8px;
}

select {
  padding: 8px;
  border-radius: 4px;
  border: 1px solid #ccc;
}

.quality-control, .size-control {
  margin: 10px 0;
}
.size-control input {
  padding: 8px;
  border-radius: 4px;
  border: 1px solid #ccc;
  margin: 0 8px;
}

button {
  width: 150px;
  padding: 10px 20px;
  background: #42b983;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  margin: 10px auto;
}

button:disabled {
  background: #cccccc;
  cursor: not-allowed;
}

.quality-control {
  margin: 10px 0;
}

.quality-control label {
  padding-right: 8px; /* 可选：为标签和滑块之间添加一些间距 */
}

.download-btn {
  display: inline-block;
  margin: 15px 0 0 20px;
  padding: 10px 20px;
  background: #2c8ef2;
  color: white;
  text-decoration: none;
  border-radius: 5px;

}

.upload-input {
  margin: 20px auto;
  width: 150px;
  padding: 10px;
  border-radius: 4px;
  display: block;
}
@media (max-width: 576px) {
  .preview-container {
    grid-template-columns: 1fr;
  }
  .size-control label {
    display: block;
    margin-bottom: 5px;
  }
}
</style>
